home *** CD-ROM | disk | FTP | other *** search
- #include <minimal.h>
- #include <osbind.h>
- #include <string.h>
-
- #define TRUE 1
- #define FALSE 0
-
- #define NULL 0
- #define FILENAME_MAX 128
-
- extern char *syserr(long);
-
- #define DIRSEP(c) (((c) == '\\') || ((c) == '/'))
-
- int
- do_cp(char *src,char *dest,int destisdir) {
- long size, rsize, wsize;
- int srcfd = 0, destfd = 0;
- char *buf = NULL;
- long bsize;
- char *e, *efile;
- long err;
- char attr;
- int datime[2];
- char destname[FILENAME_MAX], *d;
- char *s, *srcname;
- int firstflag;
-
- /*
- * if the dest is a directory:
- * put a backslash on the end if there isn't one there already,
- * set srcname past the last path separator in src (or src itself),
- * copy the last component of src after the trailing backslash,
- * set dest to this constructed filename.
- */
-
- if (destisdir) {
- strcpy(destname,dest);
- for (d = destname; *d; d++) ;
- if (!DIRSEP(*(d-1))) *d++ = '\\';
- for (srcname = s = src; *s; s++) {
- if (DIRSEP(*s)) srcname = s+1;
- }
- strcpy(d,srcname);
- dest = destname;
- }
-
- efile = src;
- if ((err = srcfd = Fopen(src,0)) < 0) goto error;
- if ((err = attr = Fattrib(src,0,0)) < 0) goto error;
- if ((err = size = Fseek(0L,srcfd,2)) < 0) goto error;
- if (err = Fseek(0L,srcfd,0)) goto error;
- if (err = Fdatime(datime,srcfd,0)) goto error;
-
- bsize = size;
- do {
- if (buf = (char *)Malloc(bsize)) break;
- bsize /= 2;
- } while (bsize >= 512);
-
- if (buf == NULL) {
- e = "no memory";
- goto error1;
- }
-
- /* We play games with firstflag so the dest file isn't created */
- /* until the source file has been opened, the memory allocated, and */
- /* the first buffer-full has actually been read. */
-
- firstflag = 1;
- while (1) {
- efile = src;
-
- if ((err = rsize = Fread(srcfd,bsize,buf)) < 0) goto error;
-
- efile = dest;
-
- if (firstflag) {
- if ((err = destfd = Fcreate(dest,0)) < 0) goto error;
- firstflag = 0;
- }
-
- /* rsize == 0 if we're done. */
- /* File might be empty so break after creating dest. */
- if (rsize == 0) break;
-
- if ((err = wsize = Fwrite(destfd,rsize,buf)) < 0) goto error;
- else if (wsize != rsize) {
- e = "write error (disk full?)";
- goto error1;
- }
- }
-
- efile = dest;
- if (err = Fdatime(datime,destfd,1)) goto error;
- if (err = Fclose(destfd)) goto error;
- destfd = 0;
- if ((err = Fattrib(dest,1,attr)) < 0) goto error;
- efile = src;
- if (err = Fclose(srcfd)) goto error;
- srcfd = 0;
-
- (void)Mfree(buf);
- return 0;
-
- error:
- e = syserr(err);
- error1:
- (void)Fwrite(2,(long)strlen(efile),efile);
- (void)Fwrite(2,2L,": ");
- (void)Fwrite(2,(long)strlen(e),e);
- (void)Fwrite(2,2L,"\r\n");
- if (srcfd) (void)Fclose(srcfd);
- if (destfd) (void)Fclose(destfd);
- if (buf) (void)Mfree(buf);
- return 1;
- }
-
- #define haswild(s) (strchr(s,'*') || strchr(s,'?'))
-
- int
- main(int argc,char *argv[])
- {
- char *p;
- int e;
- int destisdir;
- char *s, *lastcomp;
-
- --argc, ++argv;
- while (*argv && **argv == '-') {
- p = &argv[0][1];
- while (*p) {
- switch (*p) {
- case 'r': (void)Fwrite(2,23L,"cp -r not implemented\r\n");
- exit(1);
- default:
- (void)Fwrite(2,16L,"Unknown option: ");
- (void)Fwrite(2,1L,p);
- (void)Fwrite(2,2L,"\r\n");
- goto usage;
- }
- p++;
- }
- argc--, argv++;
- }
-
- if (argc < 2) {
- usage:
- (void)Fwrite(2,34L,"Usage: cp [-r] srcfiles ... dest\r\n");
- Pterm(1);
- }
-
- /* set p to point to the last arg; see if it's a directory */
- p = argv[argc-1];
- destisdir = 0;
-
- /* dest is a dir if the name is two letters long & ends with ':' */
- if (*p && *(p+1) == ':' && !*(p+2)) {
- destisdir = 1;
- goto gotdir;
- }
-
- for (lastcomp = s = p; *s; s++) {
- if (DIRSEP(*s)) lastcomp = s+1;
- }
-
- /* dot and dot-dot are directories (trust me), and if */
- /* the name ends with a DIRSEP it's a directory too. */
-
- if (!*lastcomp ||
- (*lastcomp == '.' &&
- (*(lastcomp+1) == '.' || (*(lastcomp+1)) == '\0'))) {
- destisdir = 1;
- }
- else if (!haswild(p) && (Fsfirst(p,-1) == 0)) {
- destisdir = ((struct _dta *)Fgetdta())->dta_attribute & 0x10;
- }
-
- gotdir:
- if (argc == 2) {
- return do_cp(argv[0],argv[1],destisdir);
- }
-
- if (!destisdir) {
- (void)Fwrite(2,30L,"last arg must be a directory\r\n");
- Pterm(1);
- }
-
- e = 0;
- while (argc > 1) {
- e |= do_cp(*argv,p,1);
- argv++, argc--;
- }
- return (e != 0);
- }
-
-